home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Utilities / Converters / Convert_FONT / Source / PreFontConverter.m < prev   
Text File  |  1995-06-12  |  13KB  |  382 lines

  1. /***********************************************************************
  2. Controller class for Convert FONT which converts Mac fonts to NeXT fonts.
  3. Copyright (C) 1993 David John Burrowes
  4.  
  5. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version.
  6.  
  7. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  8.  
  9. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  10.  
  11. The author, David John Burrowes, can be reached at:
  12.     davidjohn@kira.net.netcom.com
  13.     David John Burrowes
  14.     1926 Ivy #10
  15.     San Mateo, CA 94403-1367
  16. ***********************************************************************/
  17.  
  18.  
  19.  
  20. #import "PreFontConverter.h"
  21. #import "FontConverter.h"
  22. #import "PSFile.h"
  23. #import "TextFile.h"
  24. #import <appkit/Cell.h>    // for menu enabling.
  25. #import <appkit/Matrix.h>
  26.  
  27. #import <stdio.h>
  28. #import <libc.h>            // for mkdir  and rmdir
  29. #import    <string.h>        // for strrchr
  30. #import <errno.h>        // 93.01.24    for errno
  31.  
  32. @implementation PreFontConverter
  33.  
  34.  
  35. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  36. //    Routine:        init
  37. //    Parameters:    none
  38. //    Returns:        self
  39. //    Stores:        none
  40. //    Description:
  41. //        This overrides the defalut init method.  The purpose of this overriding
  42. //        is to give ourselves a chance to set up some internal variables which are used
  43. //        later on, and allocate the converter instance.
  44. //    Bugs:
  45. //    History
  46. //        93.03.14    Added code for encoding vector choice
  47. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  48. - init
  49. {    
  50.     static NXDefaultsVector theDefaults =
  51.     {
  52.         {USENSENCODING, "YES"},
  53.     };
  54.  
  55.     [super init];
  56.  
  57.     ConversionString = "Converting Mac FONT to Type 3 PS font";
  58.     SourcePrompt = "FONT file:";
  59.     DestPrompt = "Type 3 file:";
  60.     DestExtension = ".font";
  61.     
  62.     DefaultsOwner = "ConvertFONT";
  63.     NXRegisterDefaults(DefaultsOwner, theDefaults);
  64.     UseNSEncoding = [self   GetBoolPref: USENSENCODING];
  65.  
  66.     converterInst = [[FontConverter alloc] init];
  67.     return self;
  68. }
  69.  
  70.  
  71. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. //    Routine:        free
  73. //    Parameters:    none
  74. //    Returns:        a null instance
  75. //    Stores:        none
  76. //    Description:
  77. //        This simply free's the converter instance, which we allocated in the init.
  78. //    Bugs:
  79. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  80. - free
  81. {
  82.     if (converterInst != NullInstance)
  83.         [converterInst    free];
  84.     [super   free];
  85.     return NullInstance;
  86. }
  87.  
  88.  
  89. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  90. //    Routine:        displayPreferences: 
  91. //    Parameters:    the object that called us
  92. //    Returns:        self
  93. //    Stores:        none
  94. //        This is called whenever we need to bring the preferences panel onto the screen.
  95. //        Using the value in our preferences variable, we set the button in
  96. //        the preferences panel to reflect the current value, and then shows the panel.
  97. //    Bugs:
  98. //        As pointed out elsewhere, we don't really need to do this after the first time,
  99. //        since the buttons keep their own state.  So this paradigm needs revising!!
  100. //    History
  101. //        93.03.14    Created
  102. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  103. -displayPreferences: target
  104. {
  105.     //
  106.     //    Get the default preference values, and compare judge what buttons to
  107.     //    highlight for the user.
  108.     //
  109.     if (UseNSEncoding == YES)
  110.         [EncodingButton  selectCellWithTag: 0];
  111.     else
  112.         [EncodingButton  selectCellWithTag: 1];
  113.     //
  114.     //    Display the panel for the user.
  115.     //
  116.     [prefPanel    makeKeyAndOrderFront:self];
  117.     return self;
  118. }
  119.  
  120.  
  121. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  122. //    Routine:        ChangeEncodingVector: 
  123. //    Parameters:    the object that called us
  124. //    Returns:        self;
  125. //    Description:
  126. //        This method gets called whenever the user clicks on a button to change
  127. //        the setting of whether to use the NS or the Mac encoding.  If the button they
  128. //        clicked on had a key of '1', then we will use NS, otherwise we don't.
  129. //    History
  130. //        93.03.14    Created
  131. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. -ChangeEncodingVector: sender
  133. {
  134.     if ( [[sender selectedCell] tag] == 0)
  135.         UseNSEncoding = YES;
  136.     else
  137.         UseNSEncoding = NO;
  138.  
  139.     [self   SetBoolPref: USENSENCODING To: UseNSEncoding];
  140.  
  141.     return self;
  142. }
  143.  
  144.  
  145.  
  146. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  147. //    Routine:        openDestFile
  148. //    Parameters:    the path to the file to be opened
  149. //    Returns:        the opened file object  (or junk if error is TERMINALERROR()
  150. //    Stores:        errors
  151. //    Description:
  152. //        This is used to open the destination file object (a PS file).  This is needed so
  153. //        that our superclass, when it is doing some of the work that we don' want to,
  154. //        will open an instance of the right class.
  155. //    Bugs:
  156. //    History:
  157. //        93.01.10    djb    Added last minute name processing.  Specifically, give the font converter
  158. //                    the full name with spaces, and other illegal characters.  then, expanded
  159. //                    original 'replace spaces with _'s' with 'remove all delimiters and other
  160. //                    evil characters'
  161. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. - openDestFile: (CString) theFile
  163. {
  164.     CString            pathname;
  165.     CString            theDir;
  166.     CString            filename;
  167.     CString            location;
  168.     Instance            fontFile    = NullInstance;
  169.     PositiveInteger    index;
  170.     PositiveInteger    destIndex;
  171.     Integer            result;
  172.     CString            buffer;
  173.     [self  ResetResults];
  174.     //
  175.     //    Build some names needed.  If   theFile is: /foo/bar/ginger.font  then this builds:
  176.     //        filename:   ginger
  177.     //        theDir: /foo/bar/
  178.     //    And then we create the files
  179.     //        $theDir/$filename.font
  180.     //        $theDir/$filename.font/$filename
  181.     //        $theDir/$filename.font/$filename.afm
  182.     //
  183.     //    First, obtain the directory name.  (nuke everything after the final /.
  184.     //
  185.     theDir = NewCString(strlen(theFile));    // max possible size for the directory name
  186.     strcpy (theDir, theFile);
  187.     location = strrchr(theDir, '/');
  188.     location[0] = EndOfCString;
  189.     //
  190.     //    Now, build the base filename, find the last /, and copy all the rest over, and then
  191.     //    find the last period, and put a terminator there 
  192.     //
  193.     filename = NewCString(strlen(theFile));    // max possible size for file basename =)
  194.     location = strrchr(theFile, '/');
  195.     strcpy (filename, &(location[1]));
  196.     location = strrchr(filename, '.');
  197.     location[0] = NullCharacter;
  198.     //
  199.     //    Let the actual font converter know what the actual font name should be, so it
  200.     //    can store it in the afm file.  We could store this name and send it to it later, but this
  201.     //    seems like as good a time as any.  
  202.     //
  203.     [converterInst   SetFullNameTo: filename];
  204.     //
  205.     //    Remove all those characters in the name that may cause the font to be misprocessed.
  206.     //    The list I'm now aware of is: (, ), <, >, [, ], {, }, \, %.  Also, space because it breaks
  207.     //    up the name in the PS file, and period and backslash because they mess up the
  208.     //    filename, and finally single quotes because they make me uncomfortable
  209.     //    Replace all these characters with nothing    //
  210.     destIndex = 0;
  211.     for (index = 0; index < strlen(filename); index++)
  212.     {
  213.         if ((filename[index] != ' ') &&
  214.             (filename[index] != '.') &&
  215.             (filename[index] != '`') &&
  216.             (filename[index] != '\'') &&
  217.             (filename[index] != '(') &&
  218.             (filename[index] != '<') &&
  219.             (filename[index] != '[') &&
  220.             (filename[index] != '{') &&
  221.             (filename[index] != '}') &&
  222.             (filename[index] != ']') &&
  223.             (filename[index] != '>') &&
  224.             (filename[index] != ')') &&
  225.             (filename[index] != '\\') &&
  226.             (filename[index] != '/') &&
  227.             (filename[index] != '%'))
  228.         {
  229.             filename[destIndex] = filename[index];
  230.             destIndex++;
  231.         }
  232.     }
  233.     filename[destIndex] =EndOfCString;
  234.     //
  235.     //    Create a directory for the font files by
  236.     //        1) getting the file's basename (now done above)
  237.     //        2) Creating a directory with the name of the requested font
  238.     //        3) Create a font file in said directory
  239.     //        4) Create a .afm file in said directory
  240.     //
  241.     //
  242.     //        2) Creating a directory with the name of the requested font
  243.     //
  244.     pathname = NewCString(strlen(theFile)+5);// 5 extra incase no .font thefile
  245.     sprintf(pathname, "%s/%s.font", theDir, filename);
  246.     errno = 0;
  247.     result = mkdir(pathname, 0700 | 0070 | 0007); // strange perms
  248.     FreeCString(pathname);
  249.     if (result != 0)
  250.     {
  251.         buffer = NewCString(100);
  252.         sprintf(buffer,  "The font folder could not be created. (mkdir error: %d)", errno);
  253.         [self   StoreErrorCode: ERR_CREATEFAILED  AndText:buffer];
  254.         FreeCString(filename);
  255.         FreeCString(theDir);
  256.         FreeCString(buffer);
  257.         rmdir(theFile);
  258.     }
  259.     else
  260.     {
  261.         //
  262.         //    Allocate space for path to font folder, plus font or font.afm name
  263.         //
  264.         pathname = NewCString(strlen(theFile) + 5 + 1 + strlen(filename)+4);
  265.         sprintf(pathname, "%s/%s.font/%s", theDir, filename, filename);
  266.         //
  267.         //        3) Create a font file in said directory
  268.         //
  269.         fontFile =  [[PSFile alloc] initAndUse: pathname];
  270.         if ([fontFile GetErrorCode] == ERR_OK)
  271.             [fontFile CreateAndOpenFor: FILE_WRITE];
  272.         if ([fontFile GetErrorCode] != ERR_OK)
  273.         {
  274.             [self   StoreErrorCode: ERR_CREATEFAILED
  275.                 AndText: "We failed to create the PS font file"];
  276.             fontFile = NullInstance;
  277.             rmdir(theFile);
  278.         }
  279.         else
  280.         {
  281.             //
  282.             //        4) Create a .afm file in said directory
  283.             //
  284.             strcat(pathname, ".afm");
  285.             afmFile =  [[TextFile alloc] initAndUse: pathname];
  286.             if ([afmFile GetErrorCode] == ERR_OK)
  287.                 [afmFile CreateAndOpenFor: FILE_WRITE];
  288.             if ([afmFile GetErrorCode] != ERR_OK)
  289.             {
  290.                 [self   StoreErrorCode: ERR_CREATEFAILED
  291.                     AndText: "We failed to create the font's afm file."];
  292.                 [fontFile      CloseAndDelete];
  293.                 [fontFile   free];
  294.                 rmdir(theFile);
  295.                 afmFile = NullInstance;
  296.             }
  297.         }
  298.         FreeCString(pathname);
  299.     }
  300.     return fontFile;
  301. }
  302.  
  303.  
  304. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  305. //    Routine:        closeDestFile:andDelete:
  306. //    Parameters:    the path to the file to be opened
  307. //    Returns:        the opened file object  (or junk if error is TERMINALERROR()
  308. //    Stores:        errors
  309. //    Description:
  310. //        This is used to open the destination file object (a PS file).  This is needed so
  311. //        that our superclass, when it is doing some of the work that we don' want to,
  312. //        will open an instance of the right class.
  313. //    Bugs:
  314. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  315. - closeDestFile: fileInstance  andDelete: (Boolean) deleteit
  316. {
  317.     CString    thepath;
  318.  
  319.     [self   ResetResults];
  320.  
  321.     if (deleteit == NO)
  322.     {
  323.         [fileInstance   CloseAndSave];
  324.         [afmFile   CloseAndSave];
  325.     }
  326.     else
  327.     {
  328.         thepath = [fileInstance   GetDirectory];
  329.         [fileInstance   CloseAndDelete];
  330.         [afmFile   CloseAndDelete];
  331.         rmdir(thepath);
  332.         FreeCString(thepath);
  333.     }
  334.  
  335.     [self   StoreErrorCode: [fileInstance  GetErrorCode]
  336.         AndText:  [fileInstance  GetErrorText]];
  337.     [fileInstance   free];
  338.     [afmFile   free];
  339.  
  340.     return self;
  341. }
  342.  
  343.  
  344. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  345. //    Routine:        ConvertFrom:To: 
  346. //    Parameters:    The file to be converted from, and the file to be converted to
  347. //    Returns:        self
  348. //    Stores:        error code
  349. //    Description:
  350. //        This merely acts (like the rest of this object) as a kinda minimal interface
  351. //        shell.  This merely creates the converting object, asks it to convert the stuff,
  352. //        stores whether there were any results, and returns.
  353. //    Bugs
  354. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  355. - ConvertFrom: sourceFile To: destinationFile
  356. {
  357.  
  358.     [self   ResetResults];
  359.     [super   ConvertFrom: sourceFile To: destinationFile];
  360.  
  361.     [ConvertCommand    setEnabled: NO];
  362.     //
  363.     //    93.0314    Added SetNSEncodingUse call
  364.     //
  365.     [converterInst  SetNSEncodingUse:  UseNSEncoding];
  366.     [converterInst ConvertMacFONT: sourceFile
  367.         ToType3Font: destinationFile AndAFM: afmFile];
  368.  
  369.     if ( [converterInst   GetErrorCode] < ERR_OK)
  370.         [self   StoreErrorCode:  [converterInst   GetErrorCode]
  371.             AndText:  [converterInst   GetErrorText] ];
  372.     else
  373.         [self   StoreErrorCode: ERR_OK
  374.             AndText: "Converted Successfully" ];
  375.  
  376.     [ConvertCommand    setEnabled: YES];
  377.  
  378.     return self;
  379. }
  380.  
  381. @end
  382.